package Algoritmos;


import java.awt.List;
import java.io.InputStream;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Vector;

import Utiles.DataFactory;



import estructuras.common.Almacen;
import estructuras.common.Conexion;
import estructuras.common.Continente;
import estructuras.common.Fecha;
import estructuras.common.Paquete;


public class Simulator {
	Solver solver;
	GeneradorDeEstadisticas estadisticas;
	
	public Simulator(Solver solver){
		this.solver = solver;
	}
	
	public void run( DataFactory factory ){
		
		Vector< Almacen > almacenes = factory.getAlmacenes();
		Vector< Conexion> conexiones = factory.getConexiones();
		Vector< Continente > continentes = factory.getContinentes();
		Fecha fechaFin = factory.getFechaFin();
		Fecha fechaInicio = factory.getFechaInicio();
		Fecha inicioUniverso = new Fecha(0, 0 );
		solver.setFechaInicialSimulacion( fechaInicio );
		solver.setFechaFinSimulacion( fechaFin );
		solver.setFechaInicioUniverso( inicioUniverso );
		for( Continente c : continentes )
			solver.addContinente( c.getNombre() );

		for( Almacen a : almacenes ) 
			solver.addAlmacen( a.getNombre() , a.getCapacidadEnInstanteDeTiempo( fechaInicio ),
							   solver.getContinentePorNombre( a.getContinente().getNombre() ) );
		for( Conexion c : conexiones ){
			solver.addConexion( c.getOrigen() , c.getDestino() , c.getHoraDeVuelo()  , c.getFrecuencia() ,
								c.getCapacidadEnInstanteDeTiempo( fechaInicio ));
		}
		
		//meter distribuciones y data historica
		for(Almacen a : solver.getAlmacenes())
			for(Almacen b: solver.getAlmacenes()) if(a != b){;
						Almacen aa = factory.findAlmacenPorNombre(a.getNombre());
						Almacen bb = factory.findAlmacenPorNombre(b.getNombre());
						int media = factory.medias.get(new AbstractMap.SimpleEntry<>(aa, bb));
						double varianza = factory.varianzas.get(new AbstractMap.SimpleEntry<>(aa, bb));
						solver.addDistribucion(a, b, media, varianza);
					}
				//Generar paquetes
				int horas = 0;
				Fecha dif = Fecha.resta( fechaFin , fechaInicio );
				horas = dif.getDia() * 24 + dif.getHora();;
				solver.generaVuelosEnIntervaloDeTiempo(fechaInicio, horas);
				solver.generaPaquetesEstimadosParaIntervaloDeTiempo(fechaInicio, fechaFin);
				solver.generaYEjecutaRutasParaIntervaloDeTiempo(fechaInicio, fechaFin);
			
				runEstadisticas();
		
	}
	
	public void run(InputStream inputStream){
		@SuppressWarnings("resource")
		Scanner in = new Scanner(inputStream);
		int n;
		//Meter fecha inicial y final y de inicio del universo
		in.nextLine();
		Fecha fechaInicio = Fecha.parseFecha(in.nextLine());
		solver.setFechaInicialSimulacion(fechaInicio);
		solver.setFechaInicioUniverso(fechaInicio);
		//Meter fecha fin
		Fecha fechaFin = Fecha.parseFecha(in.nextLine());
		//Meter continentes
		in.nextLine();
		n = Integer.parseInt(in.nextLine());
		while(n-- > 0){
			String continente = in.nextLine();
			solver.addContinente(continente);
		}
		//Meter almacenes
		in.nextLine();
		n = Integer.parseInt(in.nextLine());
		while(n-- > 0){
			String nombre = in.nextLine();
			String continente = in.nextLine();
			int capacidadInicial = Integer.parseInt(in.nextLine());
			solver.addAlmacen(nombre, capacidadInicial, solver.getContinentePorNombre(continente));
		}
		//Meter conexiones
		in.nextLine();
		n = Integer.parseInt(in.nextLine());
		while(n-- > 0){
			String origen = in.nextLine();
			String destino = in.nextLine();
			int hora = Integer.parseInt(in.nextLine());
			int capacidadInicial = Integer.parseInt(in.nextLine());
			String patron = in.nextLine();
			if(patron.length() != 7){
				System.err.println("El patron " + patron + " no tiene longitud 7 para los dias de la semana.");
				return;
			}
			boolean[] frecuencia = new boolean[7];
			for(int i = 0; i < 7; i++) frecuencia[i] = patron.charAt(i) == '0' ? false : true;
			//boolean 
			solver.addConexion(solver.getAlmacenPorNombre(origen),
					           solver.getAlmacenPorNombre(destino),
					           hora,
					           frecuencia,
					           capacidadInicial);
		}
		
		//meter distribuciones y data historica
		in.nextLine();
		for(int i = 0; i < solver.getAlmacenes().size(); i++)
			for(int j = 0; j < solver.getAlmacenes().size(); j++) if(i != j){
				String origen = in.nextLine();
				String destino = in.nextLine();
				int media = Integer.parseInt(in.nextLine());
				double varianza = Double.parseDouble(in.nextLine());
				solver.addDistribucion(solver.getAlmacenPorNombre(origen),
									   solver.getAlmacenPorNombre(destino), media, varianza);
			}
		//Generar paquetes
		int horas = 0;
		Fecha dif = Fecha.resta( fechaFin , fechaInicio );
		horas = dif.getDia() * 24 + dif.getHora();

		System.out.println("Algoritmo: " + solver.getNombre());
		solver.generaVuelosEnIntervaloDeTiempo(fechaInicio, horas);
		solver.generaPaquetesEstimadosParaIntervaloDeTiempo(fechaInicio, fechaFin);
		solver.generaYEjecutaRutasParaIntervaloDeTiempo(fechaInicio, fechaFin);
		in.close();
		
		runEstadisticas();
	}
	
	private void runEstadisticas(){
		estadisticas = new GeneradorDeEstadisticas(solver);
		estadisticas.process();
		estadisticas.print();
	}
}
